﻿using System;
using System.Collections.Generic;
using ProjetoSolo.QueroGas.Aplicacao.ServicosExternos;
using ProjetoSolo.QueroGas.Dominio.Entidades;
using ProjetoSolo.QueroGas.Dominio.Repositorios;
using ProjetoSolo.QueroGas.Infraestrutura.PersistenciaAdo;
using ProjetoSolo.QueroGas.Infraestrutura.PersistenciaAdo.Repositorios;
using ProjetoSolo.QueroGas.Infraestrutura.ServicosWeb;
using ProjetoSolo.QueroGas.Infraestrutura.Validacao;

namespace ProjetoSolo.QueroGas.Aplicacao.Servicos
{
    public static class ServicoUsuario
    {
        #region Métodos Públicos

        private static object sessao = new object();

        public static int Cadastrar(Usuario usuario)
        {
            RegraValidacao.VerificarObjetoNulo(usuario, "O parametro usuario é obrigatório");
            usuario.Validar();

            int usuarioCadastrado = 0;

            using (IContextoRepositorio contexto = new ContextoAdo("QueroGas"))
            {
                try
                {
                    IRepositorioUsuario repositorioUsuario = new RepositorioUsuario(contexto);

                    lock (sessao)
                    {
                        if (UsuarioJahExiste(usuario.Nome, repositorioUsuario))
                            throw new Exception("Já existe um usuário cadastrado com o nome informado");

                        ServicoCriptografiaMD5 servicoCriptografia = new ServicoCriptografiaMD5();
                        usuario.Senha = servicoCriptografia.Criptografar(usuario.Senha);

                        usuarioCadastrado = repositorioUsuario.Cadastrar(usuario);

                        contexto.PersistirAlteracoes();

                        IServicoNotificacao servicoNotificacao = new ServicoNotificacaoEmail();
                        servicoNotificacao.EnviarNotificacao("sac@wimoveis.com", new List<string> {usuario.Email}, "Usuario Cadastrado", "O Usuario " + usuario.Nome + " foi cadastrado com sucesso");
                    }
                }
                catch (Exception)
                {
                    contexto.DescartarAlteracoes();

                    throw;
                }
            }
            
            return usuarioCadastrado;
        }

        public static void RecuperarSenha(string nomeUsuario, string emailUsuario)
        {           
            RegraValidacao.VerificarStringVazia(nomeUsuario, "O nome do usuario está vazio.");
            RegraValidacao.VerificarStringVazia(emailUsuario, "O email informado está vazio.");

            using (IContextoRepositorio contexto = new ContextoAdo("QueroGas"))
            {
                try
                {
                    IRepositorioUsuario repositorio = new RepositorioUsuario(contexto);

                    Usuario usuario = repositorio.BuscarUsuarioPorNome(nomeUsuario);

                    if (usuario == null)
                        throw new Exception("Não foi encontrado nenhum usuário com o email informado");

                    if(!usuario.Ativo)
                        throw new Exception("O usuário que você está tentando recuperar a senha está inativo.");

                    IServicoGeracaoSenha servicoGeracaoSenha = new ServicoGeracaoSenha();
                    string novaSenha = servicoGeracaoSenha.GerarSenha();

                    IServicoCriptografia servicoCriptografia = new ServicoCriptografiaMD5();
                    usuario.Senha = servicoCriptografia.Criptografar(novaSenha);

                    repositorio.AlterarSenha(usuario.IdUsuario, usuario.Senha);

                    contexto.PersistirAlteracoes();

                    IServicoNotificacao servicoNotificacao = new ServicoNotificacaoEmail();
                    servicoNotificacao.EnviarNotificacao("sac@wimoveis.com", new List<string>() { usuario.Email }, "Recuperação de senha", novaSenha);
                }
                catch (Exception)
                {
                    contexto.DescartarAlteracoes();
                    throw;
                }
            }
        }

        public static void TrocarSenha(string nome, string senhaAntiga, string senhaNova)
        {
            RegraValidacao.VerificarStringVazia(nome, "O nome do usuário informado está vazio");
            RegraValidacao.VerificarStringVazia(senhaAntiga, "A senha antiga informada está vazia");
            RegraValidacao.VerificarStringVazia(senhaNova, "A senha nova informada está vazia");

            using (IContextoRepositorio contexto = new ContextoAdo("QueroGas"))
            {
                try
                {
                    IRepositorioUsuario repositorioUsuario = new RepositorioUsuario(contexto);
                    
                    IServicoCriptografia servicoCriptografia = new ServicoCriptografiaMD5();

                    Usuario usuario = repositorioUsuario.BuscarUsuarioPorLogin(nome, servicoCriptografia.Criptografar(senhaAntiga));

                    if(usuario == null)
                        throw new Exception("A senha antiga informada está incorreta.");
                    
                    usuario.Senha = servicoCriptografia.Criptografar(senhaNova);

                    repositorioUsuario.AlterarSenha(usuario.IdUsuario, usuario.Senha);

                    contexto.PersistirAlteracoes();
                }
                catch (Exception)
                {
                    contexto.DescartarAlteracoes();
                    throw;
                }
            }
        }

        public static int AtivarCadastro(int idUsuario)
        {
            RegraValidacao.VerificarValorZerado(idUsuario, "O id do usuario informado é inválido");

            int usuarioAtivado = 0;

            using (IContextoRepositorio contexto = new ContextoAdo("QueroGas"))
            {
                try
                {
                    IRepositorioUsuario repositorio = new RepositorioUsuario(contexto);
                    repositorio.Ativar(idUsuario);

                    contexto.PersistirAlteracoes();
                }
                catch (Exception)
                {
                    contexto.DescartarAlteracoes();
                    throw;
                }
            }

            return usuarioAtivado;
        }

        public static int InativarCadastro(int idUsuario)
        {
            RegraValidacao.VerificarValorZerado(idUsuario, "O id do usuario informado é inválido");

            int usuarioInativado = 0;

            using (IContextoRepositorio contexto = new ContextoAdo("QueroGas"))
            {
                try
                {
                    IRepositorioUsuario repositorio = new RepositorioUsuario(contexto);
                    repositorio.Inativar(idUsuario);

                    contexto.PersistirAlteracoes();
                }
                catch (Exception)
                {
                    contexto.DescartarAlteracoes();
                    throw;
                }
            }

            return usuarioInativado;
        }

        public static bool UsuarioJahExiste(string nomeUsuario)
        {
            RegraValidacao.VerificarStringVazia(nomeUsuario, "O nome do usuário está vazio.");

            bool usuarioExiste = false;

            using (IContextoRepositorio contexto = new ContextoAdo("QueroGas"))
            {
                IRepositorioUsuario repositorio = new RepositorioUsuario(contexto);
                usuarioExiste = UsuarioJahExiste(nomeUsuario, repositorio);
            }

            return usuarioExiste;
        }

        #endregion

        #region Métodos Privados

        private static bool UsuarioJahExiste(string nomeUsuario, IRepositorioUsuario repositorio)
        {
            if (repositorio.BuscarUsuarioPorNome(nomeUsuario) != null)
                return true;

            return false;
        }

        #endregion
    }
}